using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Microsoft.SharedSource.SqlServer.MDDE.Repository;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SharedSource.SqlServer.MDDE.Components;

namespace Microsoft.SharedSource.SqlServer.MDDE.Middleware
{
    public static partial class MDDEManager
    {
        #region Public Methods

        /// <summary>
        /// Creates a new template instance into the repository.
        /// </summary>
        /// <param name="repositoryConnectionString"></param>
        /// <param name="instanceName"></param>
        /// <param name="templateName"></param>
        /// <param name="changesXml"></param>
        /// <returns></returns>
        public static OperationResult AddTemplateInstance(string repositoryConnectionString,
            string instanceName, string templateName, XmlDocument changesXml)
        {
            OperationResult result = OperationResult.Empty;

            try
            {
                // Create a repository object.
                MDDERepository repository = new MDDERepository(repositoryConnectionString);

                // Get the package template.
                MDDEPackageTemplate template = repository.PackageTemplates[templateName];

                // Create a template instance.
                MDDETemplateInstance instance = new MDDETemplateInstance(template, instanceName);

                instance.ApplyProperties(changesXml, true);

                // Create the instance.
                instance.Create();

                // Enter success status into the log.
                result.SuccessStatus = true;
                result.OperationLog.Add("Successful template instance creation: Connection - " +
                    repositoryConnectionString + " Template - " + templateName);
            }
            catch (Exception ex)
            {
                result.SuccessStatus = false;
                result.OperationLog.Add("Template instance creation failed: Connection - " +
                    repositoryConnectionString + " Template - " + templateName +
                    " Error - " + ex.Message);
            }

            return result;
        }

        /// <summary>
        /// Creates a package out of the instance information.
        /// </summary>
        /// <param name="repositoryConnectionString"></param>
        /// <param name="templateName"></param>
        /// <param name="instanceName"></param>
        /// <returns></returns>
        public static OperationResult CreatePackageFromInstance(string repositoryConnectionString,
            string templateName, string instanceName)
        {
            OperationResult result = OperationResult.Empty;

            try
            {
                // Create a repository object.
                MDDERepository repository = new MDDERepository(repositoryConnectionString);

                // Get the package template.
                MDDEPackageTemplate template = repository.PackageTemplates[templateName];

                // Get the template instance.
                MDDETemplateInstance tin = template.TemplateInstances[instanceName];

                // Get the changes xml.
                XmlDocument changesXml = tin.GetChangesXml();

                // Apply changes to the package.
                Package underlyingPackage = new Package();
                underlyingPackage.LoadFromXML(template.Body, null);

                MDDEExecutionDAG underlyingPackageDag = new MDDEExecutionDAG(underlyingPackage);

                if (underlyingPackageDag.ApplyChanges(changesXml, instanceName))
                {
                    // Enter success status into the log.
                    result.SuccessStatus = true;
                    result.OperationLog.Add("Successful package creation: Connection - " +
                        repositoryConnectionString + " Template - " +
                        templateName + " Instance - " + instanceName);

                    // Enter the generated package into the output parameters.
                    result.OperationOutputParameters.Add(underlyingPackageDag.InnerComponent);
                }
                else
                {
                    result.OperationLog.Add("Package creation failed: Connection - " +
                    repositoryConnectionString + " Template - " + templateName +
                    " Instance - " + instanceName);
                    result.SuccessStatus = false;
                }

                //// Invoke the fixer.
                //XmlDocument xDoc = new XmlDocument();
                //xDoc.LoadXml(template.Body);
                //PackageFixer fixer = new PackageFixer(xDoc, changesXml, instanceName);

                //PkgFixerExecResult fixerResult = fixer.Execute();

                //if (fixerResult.Result ==
                //    Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success)
                //{
                //    // Enter success status into the log.
                //    result.SuccessStatus = true;
                //    result.OperationLog.Add(
                //        "Successful package creation: Connection - " +
                //        repositoryConnectionString +
                //        " Template - " + templateName);

                //    // Enter the generated package 
                //    // into the output parameters.
                //    result.OperationOutputParameters.Add(
                //        fixerResult.GeneratedPackge);
                //}
            }
            catch (Exception ex)
            {
                result.SuccessStatus = false;
                result.OperationLog.Add("Package creation failed: Connection - " +
                    repositoryConnectionString + " Template - " + templateName +
                    " Instance - " + instanceName +
                    " \nError - " + ex.Message);
            }

            return result;
        }

        /// <summary>
        /// Deletes a template instance.
        /// </summary>
        /// <param name="repositoryConnectionString"></param>
        /// <param name="templateName"></param>
        /// <param name="templateInstanceName"></param>
        /// <returns></returns>
        public static OperationResult DeleteTemplateInstance(string repositoryConnectionString,
            string templateName, string templateInstanceName)
        {
            OperationResult result = OperationResult.Empty;

            // Delete the package.
            try
            {

                MDDERepository repository = new MDDERepository(repositoryConnectionString);

                if (!repository.PackageTemplates.ContainsTemplate(templateName))
                {
                    result.OperationLog.Add("Template \"" + templateName +
                        "\" doesn't exists in the repository");

                    return result;
                }

                MDDEPackageTemplate template = repository.PackageTemplates[templateName];

                if (!template.TemplateInstances.ContainsTemplateInstance(templateInstanceName))
                {
                    result.OperationLog.Add("Template instance \"" +
                        templateInstanceName +
                        "\" doesn't exists in the repository");

                    return result;
                }

                MDDETemplateInstance instance = template.TemplateInstances[templateInstanceName];

                instance.Delete();

                result.SuccessStatus = true;
            }
            catch (Exception ex)
            {
                result.OperationLog.Add(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// Returns the changes xml from a template instance.
        /// </summary>
        /// <param name="repositoryConnectionString"></param>
        /// <param name="templateName"></param>
        /// <param name="templateInstanceName"></param>
        /// <returns></returns>
        public static OperationResult GetInstanceConfigurationData(
            string repositoryConnectionString, string templateName, string templateInstanceName)
        {
            OperationResult result = OperationResult.Empty;

            try
            {
                MDDERepository repository = new MDDERepository(repositoryConnectionString);

                if (!repository.PackageTemplates.ContainsTemplate(templateName))
                {
                    result.OperationLog.Add("Template \"" + templateName +
                        "\" doesn't exists in the repository");

                    return result;
                }

                MDDEPackageTemplate template = repository.PackageTemplates[templateName];

                if (!template.TemplateInstances.ContainsTemplateInstance(templateInstanceName))
                {
                    result.OperationLog.Add("Template instance \"" +
                        templateInstanceName +
                        "\" doesn't exists in the repository");

                    return result;
                }

                MDDETemplateInstance instance = template.TemplateInstances[templateInstanceName];

                // Get the changes xml.
                XmlDocument instanceConfig = instance.GetChangesXml();

                // Get the template tree.
                XmlDocument templateTree = GetPackageTree(template.Body);

                // Add entries for all the template configurable components.
                AddTemplateComponentsToChangesXml(
                    instanceConfig, template.Configuration, templateTree);

                result.OperationOutputParameters.Add(instanceConfig);

                result.SuccessStatus = true;
            }
            catch (Exception ex)
            {
                result.OperationLog.Add(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// Updates the template instance.
        /// </summary>
        /// <param name="repositoryConnectionString"></param>
        /// <param name="templateName"></param>
        /// <param name="instanceName"></param>
        /// <param name="instanceConfigurationData"></param>
        /// <returns></returns>
        public static OperationResult UpdateTemplateInstance(string repositoryConnectionString,
            string templateName, string instanceName, XmlDocument instanceConfigurationData)
        {
            OperationResult result = OperationResult.Empty;

            try
            {
                // Create a repository object.
                MDDERepository repository = new MDDERepository(repositoryConnectionString);

                // Get the package template.
                MDDEPackageTemplate template = repository.PackageTemplates[templateName];

                // Create a template instance.
                MDDETemplateInstance instance = new MDDETemplateInstance(template, instanceName);

                instance.ApplyProperties(instanceConfigurationData, false);

                // Update the instance.
                instance.Update();

                // Enter success status into the log.
                result.SuccessStatus = true;
                result.OperationLog.Add(
                    "Template instance successfully updated: Connection - " +
                    repositoryConnectionString + " Template - " + templateName);
            }
            catch (Exception ex)
            {
                result.SuccessStatus = false;
                result.OperationLog.Add(
                    "Template instance udpation failed: Connection - " +
                    repositoryConnectionString + " Template - " + templateName +
                    " Error - " + ex.Message);
            }

            return result;
        }

        #endregion
    }
}
